package io.plus.utils.lock;

import drds.common.$;
import lombok.extern.slf4j.Slf4j;

import java.io.Serializable;
import java.util.concurrent.locks.ReentrantReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock.ReadLock;
import java.util.concurrent.locks.ReentrantReadWriteLock.WriteLock;

/**
 * 自带读写锁的对象
 */
@Slf4j
public class ReadWriteLockObject<Objec> implements Serializable {
    private static final long serialVersionUID = -3048283373239453901L;
    private Objec object = null;
    private ReentrantReadWriteLock lock = null;

    public ReadWriteLockObject(Objec object) {
        this(object, new ReentrantReadWriteLock());
    }

    public ReadWriteLockObject(Objec object, ReentrantReadWriteLock lock) {
        super();
        this.object = object;
        this.lock = lock;
    }

    public ReentrantReadWriteLock getLock() {
        return lock;
    }

    /**
     * 获取写锁
     */
    public WriteLock getWriteLock() {
        return lock.writeLock();
    }

    /**
     * 获取读锁
     */
    public ReadLock getReadLock() {
        return lock.readLock();
    }

    public Objec getObject() {
        return object;
    }

    public void setObject(Objec object) {
        this.object = object;
    }
    //

    /**
     * 操作obj时，带上写锁
     */
    public void handle(WriteLockHandler<Objec> writeLockHandler) {
        WriteLock writeLock = lock.writeLock();
        writeLock.lock();
        try {
            writeLockHandler.handler(object);
        } catch (Throwable e) {
            log.error($.printStackTraceToString(e));
            throw new RuntimeException(e);
        } finally {
            writeLock.unlock();
        }
    }

    /**
     * 操作obj时，带上读锁
     */
    public void handle(ReadLockHandler<Objec> readLockHandler) {
        ReadLock readLock = lock.readLock();
        readLock.lock();
        try {
            readLockHandler.handler(object);
        } catch (Throwable e) {
            log.error($.printStackTraceToString(e));
            throw new RuntimeException(e);
        } finally {
            readLock.unlock();
        }
    }


}
